///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2007-2009 ILOG, S.A.
//  All Rights Reserved.
//  The following is ILOG Source Code.  No modifications may be made to the  
//  ILOG Source Code.  Any usage of the ILOG Source Code is subject to 
//  the terms and conditions of the ILOG End User License Agreement   
//  applicable to this ILOG software product.
//
///////////////////////////////////////////////////////////////////////////////

package ilog.gauges.rectangular.renderers
{
  import flash.display.DisplayObject;
  
  import ilog.gauges.gaugesClasses.rectangular.RectangularValueRenderer;
  
  import mx.core.IFlexDisplayObject;
  
  [DefaultProperty("asset")]

  /**
   * The <code>RectangularGaugeAsset</code> is a wrapper to include visual external 
   * assets into a rectangular gauge.
   *  
   * @mxml
   *  
   * <p>The <code>&lt;ilog:RectangularGaugeAsset&gt;</code> tag inherits all the 
   * properties of its parent classes and adds the following properties:</p>
   *  
   * <pre>
   * &lt;ilog:RectangularGaugeAsset
   *   <strong>Properties</strong>
   *   asset="<i>Class; no default</i>"
   *   mode="marker|bar|decoration"
   * /&gt;
   * </pre>
   *
   * @includeExample examples/RectangularGaugeAssetExample.mxml -noswf
   */  
  public class RectangularGaugeAsset extends RectangularValueRenderer
  {
    /**
     *  @private
     */                
    private var _assetInstance:IFlexDisplayObject;

    /**
     *  @private
     */
    private var _asset:Class;
    
    [Inspectable(category="Gauge")]
    
    /**
     * The class of the asset. Typically, you include SWF assets
     * with the <code>[Embed]</code> tag and pass the obtained class to this attribute.
     * The class must implement the <code>IFlexDisplayObject</code> interface,
     * which is the case for all assets embedded using the <code>[Embed]</code> tag and 
     * <code>ProgrammaticSkin</code>.
     */                       
    public function get asset():Class
    {
      return _asset;
    }

    /**
     *  @private
     */
    public function set asset(value:Class):void
    {
      if (_assetInstance != null) {
        removeChild(_assetInstance as DisplayObject);
        // invalidate for commitProperties to re-create it
        _assetInstance = null;
      }
      _asset = value;
      invalidateProperties();
    }
    
    private var _mode:String = "marker";
    
    [Inspectable(category="Gauge", enumeration="marker,bar,decoration", defaultValue="marker")]
    
    /**
     * The mode used to lay out the asset. Possible values are:
     * <ul>
     * <li><code>"marker"</code> (default): If the gauge is horizontal, the asset is drawn around the position 
     * that corresponds to the value of this renderer using its measured width and is
     * stretched vertically to match the renderer height. If the gauge is vertical,
     * the asset is drawn around the position that corresponds to the value
     * of this renderer using its measured height and stretched horizontally to 
     * match the renderer width.</li>
     * <li><code>"bar"</code>: If the gauge is horizontal, the asset is stretched horizontally to go from
     * the minimum position to the position corresponding to the value and vertically
     * to match the renderer height. If the gauge is vertical, the asset is stretched vertically
     * to go from the minimum position to the position corresponding to the value and
     * horizontally to match the renderer width.</li>
     * <li><code>"decoration"</code>: The asset is stretched to match the width
     * and height of the renderer.</li>
     * </ul>
     * 
     * @default "marker"
     * @see MarkerRenderer
     * @see RectangularBarRenderer
     * @see RectangleRenderer
     */
    public function get mode():String
    {
      return _mode;
    }
    
    public function set mode(value:String):void
    {
      _mode = value;
      invalidateDisplayList();
    }
    
    /**
     * @private
     */
    protected override function commitProperties():void
    {
      super.commitProperties();
      if (_asset != null && _assetInstance == null) {
        _assetInstance = new _asset();
        //_
        addChild(_assetInstance as DisplayObject);
      }    
    }    
        
    /**
     * @private
     */        
    protected override function measure():void
    {
      measuredWidth = 0;
      measuredHeight = 0;                
      if (_assetInstance != null) {
        measuredWidth = _assetInstance.measuredWidth; 
        measuredHeight = _assetInstance.measuredHeight;
      }         
    }    
    
    /**
     * Draws the asset at the right position.
     * 
     * @param unscaledWidth Specifies the width, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleX</code> property of the component.
     *
     * @param unscaledHeight Specifies the height, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleY</code> property of the component. 
     */      
    protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
      // call super in case we are the master to update the scale     
      super.updateDisplayList(unscaledWidth, unscaledHeight);
            
        
      if (_assetInstance != null) {
        if (_mode == "decoration") {
          _assetInstance.move(0, 0);
          _assetInstance.setActualSize(unscaledWidth, unscaledHeight);
        } else {
          var pos:Number = isNaN(transitionPosition) ? scale.positionForValue(value) : 
                                                       transitionPosition;
          if (_mode == "marker") {
            if (gauge.direction == "horizontal") {              
              _assetInstance.move(pos - _assetInstance.measuredWidth / 2, 0);
              _assetInstance.setActualSize(_assetInstance.measuredWidth,
                                             unscaledHeight);
            } else {
              _assetInstance.move(0, (unscaledHeight - pos) - _assetInstance.measuredHeight / 2);
              _assetInstance.setActualSize(unscaledWidth,
                                               _assetInstance.measuredHeight);                 
            }
          } else {            
            // bar
            var init:Number = scale.positionForValue(scale.majorTickItems[0].value);
            if (gauge.direction == "horizontal") {
              _assetInstance.move(init, 0);
              _assetInstance.setActualSize(pos - init, unscaledHeight);  
            } else {
              _assetInstance.move(0, unscaledHeight - pos);
              _assetInstance.setActualSize(unscaledWidth, pos - init);
            }
          }                             
        } 
      }
    }

  }
}
